/* Copyright ©, 2022, ECARX (Hubei) Technology Co., Ltd. All rights reserved.
 *
 * NOTICE: This file contains information which is confidential and proprietary to ECARX
 * (Hubei) Technology Co., Ltd. and/or other developers. No license to any intellectual
 * property rights contained within this file is either granted or implied except as may be
 * provided in an agreement with ECARX (Hubei) Technology Co., Ltd.
 *
 * Any unauthorized copying or distribution of content from this file in whole or in part
 * is prohibited.
 */
#define LOG_NDEBUG 0
#define LOG_TAG "VHalCore"
#include "vhal_core/VHalCore.h"
#include "VHalLog.h"

#include "VendorVehicleServer.h"
#include <android-base/properties.h>

namespace ecarx::vhal::core {

//最小的超时等待时间(单位:毫秒)
constexpr const int32_t MIN_TIMEOUT = 3000;

class VHalCore::CoreImpl {
    std::unique_ptr<impl::VendorVehicleServer> mVhalImpl;
    //启动锁
    mutable std::mutex mStartMutex;
    std::condition_variable mCond;

  public:
    CoreImpl(const Config& config) : mVhalImpl(std::make_unique<impl::VendorVehicleServer>()) {
        mVhalImpl->setPlatformProfile(config.getProfileImpl());
        mVhalImpl->setDID(new persist::DID(config.getDIDDir().c_str()));
        mVhalImpl->setTransfers(config.getTransfers());
    }

    interface::IVendorVehicleServer* startForWait(int32_t milliseconds) {
        int32_t timer = milliseconds < MIN_TIMEOUT ? MIN_TIMEOUT : milliseconds;
        if (mVhalImpl->getRunMode() == impl::RunMode::AOSP) {
            VHALOG.d("before openTransfer startForWait by aosp mode");
            int count = 0;
            std::string initVlanReady = android::base::GetProperty("init.vlan.ready", "");
            VHALOG.d("dbgstart start check init.vlan.ready 15s");
            while (initVlanReady != "1" && count < 300) {
                std::this_thread::sleep_for(std::chrono::milliseconds(50));
                initVlanReady = android::base::GetProperty("init.vlan.ready", "");
                count++;
            }
            VHALOG.d("dbgstart check init.vlan.ready = %s", initVlanReady.c_str());
            std::unique_lock<std::mutex> lock(mStartMutex);
            mVhalImpl->openTransfers([this]() {
                VHALOG.d("dbgstart transfer data ready callback");
                mCond.notify_one();
            });
            VHALOG.d("dbgstart begin wait transfer data ready");
            if (mCond.wait_for(lock, std::chrono::milliseconds(timer)) == std::cv_status::timeout) {
                VHALOG.d("dbgstart wait transfer data ready time out by %dms", timer);
            } else {
                VHALOG.d("dbgstart transfer data ready < timeout %dms", timer);
            }
        } else {
            VHALOG.d("startForWait by debug mode");
            mVhalImpl->openTransfers();
        }
        mVhalImpl->initAllProperties();
        return mVhalImpl.get();
    }

};

VHalCore::VHalCore(const Config& config) : mImpl(new CoreImpl(config)) {}

VHalCore::~VHalCore() {
    delete mImpl;
}

interface::IVendorVehicleServer* VHalCore::startForWait(int32_t milliseconds) {
    return mImpl->startForWait(milliseconds);
}


}  // namespace ecarx::vhal::core
